<?php
	/**
	 *	Kris' Lightweight Framework (KLF)
	 *
	 *	@author Kristian Oye <kristianoye@gmail.com> 
	 *	@copyright (C) 2010-2011, Kristian Oye
	 */
	namespace KLF\System
	{
		use KLF\System\Errors\KArgumentException;

		/**
		 *  Class KComponent
		 *
		 *  The basis for heavier objects
		 *
		 *  @package KLF\System
		 *  @access public
		 *  @author Kristian Oye <kristianoye@gmail.com>
		 *  @since 0.1
		 *  
		 *  @method KComponent NewInstance
		 */
		class KComponent extends KObject
		{
			private $_Mixins;
			
			/**
			 * KComponent constructor
			 *
			 * @author Kristian Oye <kristianoye@gmail.com>
			 * @since 0.1
			*/
			public function __construct()
			{
				$this->_Mixins = array();
				
				parent::__construct();
			}
			
			/**
			 * Adds an event listener if such an event exists.
			 *
			 * @author Kristian Oye <kristianoye@gmail.com>
			 * @since 0.1
			 * @return bool True if the listener was added, false if not
			*/
			public function AddEventListener($eventName, $listener)
			{
				$event = $this->GetEvent('event' . $eventName);
				if (!isset($event))
				{
					throw new Errors\KEventException($eventName, $this);
				}
				else
				{
					if(!is_callable($listener))
					{
						throw new Errors\KArgumentException("AddEventListener() argument 2 must be callable.");
					}
					return $event->AddListener($listener);
				}				
			}
			
			/**
			 * Adds a mixin behavior to the component.
			 * 
			 * @author Kristian Oye <kristianoye@gmail.com>
			 * @since 0.1
			 */
			protected final function AddMixin($mixin)
			{
				array_push($this->_Mixins, $mixin);
			}
			
			/**
			 * Returns an event object if one exists.
			 * @param string $eventName The name of the event.
			 * @return KEvent
			 */
			protected function GetEvent($eventName)
			{
				$eventName = "_$eventName";
				
				if(isset($this->$eventName))
				{
					$event = $this->$eventName;
					
					if (is_a($event, '\KLF\System\KEvent'))
						return $event;
				}
				return NULL;
			}

			/**
			 * Removes a mixin behavior
			 *
			 * @author Kristian Oye <kristianoye@gmail.com>
			 * @since 0.1
			 * @return boolean True if successful, false if not
			*/
			protected final function RemoveMixin()
			{
				return false;
			}

			/**
			 * Magic method that allows events and mixins to work.
			 * 
			 * @param string $name The name of the virtual method being called.
			 * @param array $args The parameters being passed to the method.
			 * @throws \KLF\System\Errors\KMethodException
			 */
			public function __call($name, $args)
			{
				if(substr($name, 0, 5) === 'event')
				{
					$event = $this->GetEvent($name);
											
					if(isset($event))
					{
						$result = call_user_func_array($event, array($this, $args));
						
						if (method_exists($this, $onMethod = "On" . substr($name, 5)))
						{
							call_user_func_array(array($this, $onMethod), array($this, $event));
						}
						
						if (isset($result) && !is_null($result))
							return $result;
						
						return null;
					}
				}
				else
				{
					throw new Errors\KMethodException($name, $this);
				}
			}
		}
	}